// VocoderGUIDlg.cpp : implementation file
//

#include "stdafx.h"

#include "../SAPIAdapter/VoiceNames.h"
#include "../SAPIAdapter/SAPIController.h"
#include "../SFMLAdapter/Recorder.h"

#include "VocoderGUI.h"
#include "VocoderGUIDlg.h"
#include "VocoderController.h"
#include "SAPIModulator.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	enum { IDD = IDD_ABOUTBOX };

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support

// Implementation
protected:
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()


// CVocoderGUIDlg dialog




CVocoderGUIDlg::CVocoderGUIDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CVocoderGUIDlg::IDD, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

WCHAR* CVocoderGUIDlg::NextText()
{
	return (WCHAR*) lastText.c_str();
}


void CVocoderGUIDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_SLIDER_FREQ, sliderFrequency);
	DDX_Control(pDX, IDC_SLIDER_WN, sliderWhiteNoise);
	DDX_Control(pDX, IDC_SLIDER_TRI, sliderTriangular);
	DDX_Control(pDX, IDC_SLIDER_SQUARE, sliderSquare);
	DDX_Control(pDX, IDC_SLIDER_SAW, sliderSawtooth);
	DDX_Control(pDX, IDC_SLIDER_SINE, sliderSine);
	DDX_Control(pDX, IDC_COMBO_OUTPUT, comboOutput);
	DDX_Control(pDX, IDC_SLIDER_FREQVAR, sliderFreqVar);
	DDX_Control(pDX, IDC_SLIDER_RANDOM, sliderRandom);
	DDX_Control(pDX, IDC_SLIDER_BROWNNOISE, sliderBrownNoise);
	DDX_Control(pDX, IDC_SLIDER_SINEF2, sliderSineF2);
	DDX_Control(pDX, IDC_SLIDER_SINE_F3, sliderSineF3);
	DDX_Control(pDX, IDC_SLIDER_SINE_F4, sliderSineF4);
	DDX_Control(pDX, IDC_SLIDER_SINE_F5, sliderSineF5);
	DDX_Control(pDX, IDC_SLIDER_SINE_F6, sliderSineF6);
	DDX_Control(pDX, IDC_SLIDER_SINE_F7, sliderSineF7);
	DDX_Control(pDX, IDC_SLIDER_FUNC1, sliderFunc1);
	DDX_Control(pDX, IDC_SLIDER_FUNC2, sliderFunc2);
	DDX_Control(pDX, IDC_SLIDER_FUNC3, sliderFunc3);
	DDX_Control(pDX, IDC_EDIT_MODULATOR, editModulator);
	DDX_Control(pDX, IDC_CHECK_RECORD, checkRecord);
	DDX_Control(pDX, IDC_EDIT_AMP_THRES, ptAmplitudeThreshold);
	DDX_Control(pDX, IDC_EDIT_NOISE_THRES, ptNoiseThreshold);
	DDX_Control(pDX, IDC_COMBOVOICE, comboVoice);
}

BEGIN_MESSAGE_MAP(CVocoderGUIDlg, CDialog)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	//}}AFX_MSG_MAP
	ON_BN_CLICKED(IDC_BUTTON_PLAY, &CVocoderGUIDlg::OnBnClickedButtonPlay)
	ON_BN_CLICKED(IDC_BUTTON_UPDATE_MODULATOR, &CVocoderGUIDlg::OnBnClickedButtonUpdateModulator)
	ON_CBN_SELCHANGE(IDC_COMBOVOICE, &CVocoderGUIDlg::OnCbnSelchangeCombovoice)
END_MESSAGE_MAP()


// CVocoderGUIDlg message handlers

BOOL CVocoderGUIDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	/*
	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}
	*/

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon

	sliderFrequency.SetRange(55, 440);
	sliderFreqVar.SetRange(0, 10);
	sliderWhiteNoise.SetRange(0, 1000);
	sliderBrownNoise.SetRange(0, 1000);
	sliderRandom.SetRange(0, 1000);
	sliderFunc1.SetRange(0, 1000);
	sliderFunc2.SetRange(0, 1000);
	sliderFunc3.SetRange(0, 1000);
	sliderTriangular.SetRange(0, 1000);
	sliderSquare.SetRange(0, 1000);
	sliderSawtooth.SetRange(0, 1000);
	sliderSine.SetRange(0, 1000);
	sliderSineF2.SetRange(0, 1000);
	sliderSineF3.SetRange(0, 1000);
	sliderSineF4.SetRange(0, 1000);
	sliderSineF5.SetRange(0, 1000);
	sliderSineF6.SetRange(0, 1000);
	sliderSineF7.SetRange(0, 1000);

	sliderFrequency.SetPos(110);
	sliderFreqVar.SetPos(1);
	sliderWhiteNoise.SetPos(0);
	sliderBrownNoise.SetPos(0);
	sliderRandom.SetPos(100);
	sliderFunc1.SetPos(0);
	sliderFunc2.SetPos(200);
	sliderFunc3.SetPos(200);
	sliderTriangular.SetPos(400);
	sliderSquare.SetPos(150);
	sliderSawtooth.SetPos(250);
	sliderSine.SetPos(0);
	sliderSineF2.SetPos(0);
	sliderSineF3.SetPos(0);
	sliderSineF4.SetPos(0);
	sliderSineF5.SetPos(0);
	sliderSineF6.SetPos(0);
	sliderSineF7.SetPos(0);
	
	comboOutput.AddString(_T("Vocoder"));
	comboOutput.SetItemData(0, Settings::PlayerSettings::Vocoder);
	comboOutput.AddString(_T("Modulator"));
	comboOutput.SetItemData(1, Settings::PlayerSettings::Modulator);
	comboOutput.AddString(_T("Carrier"));
	comboOutput.SetItemData(2, Settings::PlayerSettings::Carrier);
	comboOutput.SelectString(0, _T("Vocoder"));

	lastText.assign(_T("The quick brown fox jumped over the lazy dog."));
	this->editModulator.SetWindowTextW(lastText.c_str());
	OnBnClickedButtonUpdateModulator();


	VoiceNames voiceNameProvider;
	std::vector<std::wstring> names;
	voiceNameProvider.GetNames(names);

	for(unsigned int i=0; i<names.size(); i++)
	{
		comboVoice.AddString(names[i].c_str());
	}
	//comboVoice.SetCurSel(0);
	//controller->GetSAPIModulator()->sapiController.SetVoiceName((WCHAR*)names[0].c_str());

	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CVocoderGUIDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CVocoderGUIDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this function to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CVocoderGUIDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}


char* TcharToChar(const TCHAR* orig)
{
    size_t origsize = wcslen(orig) + 1;
    size_t convertedChars = 0;
    const size_t newsize = origsize*2;
    char *nstring = new char[newsize];
    wcstombs_s(&convertedChars, nstring, newsize, orig, _TRUNCATE);
	return nstring;
}

TCHAR* GetTcharText(CWnd& wnd)
{
	int len = wnd.GetWindowTextLengthW();
	TCHAR* dest = new TCHAR[len+1];
	wnd.GetWindowTextW(dest, len+1);
	return dest;
}

static void GetText(CWnd& wnd, std::string& destination)
{
	int len = wnd.GetWindowTextLengthW();
	TCHAR* dest = new TCHAR[len+1];
	wnd.GetWindowTextW(dest, len+1);
	char* chDest = TcharToChar(dest);
	delete dest;
	destination.assign(chDest);
	delete chDest;
}

int CVocoderGUIDlg::GetRandom()
{
	return sliderRandom.GetPos();
}
int CVocoderGUIDlg::GetFrequency()
{
	return sliderFrequency.GetPos();
}

int CVocoderGUIDlg::GetFrequencyVariation()
{
	return sliderFreqVar.GetPos();
}
int CVocoderGUIDlg::GetBrownNoise()
{
	return sliderBrownNoise.GetPos();
}

int CVocoderGUIDlg::GetWhiteNoise()
{
	return sliderWhiteNoise.GetPos();
}
int CVocoderGUIDlg::GetFunction1()
{
	return sliderFunc1.GetPos();
}
int CVocoderGUIDlg::GetFunction2()
{
	return sliderFunc2.GetPos();
}
int CVocoderGUIDlg::GetFunction3()
{
	return sliderFunc3.GetPos();
}
int CVocoderGUIDlg::GetTriangular()
{
	return sliderTriangular.GetPos();
}
int CVocoderGUIDlg::GetSquare()
{
	return sliderSquare.GetPos();
}
int CVocoderGUIDlg::GetSawtooth()
{
	return sliderSawtooth.GetPos();
}
int CVocoderGUIDlg::GetSine()
{
	return sliderSine.GetPos();
}
int CVocoderGUIDlg::GetSineF2()
{
	return sliderSineF2.GetPos();
}
int CVocoderGUIDlg::GetSineF3()
{
	return sliderSineF3.GetPos();
}
int CVocoderGUIDlg::GetSineF4()
{
	return sliderSineF4.GetPos();
}
int CVocoderGUIDlg::GetSineF5()
{
	return sliderSineF5.GetPos();
}
int CVocoderGUIDlg::GetSineF6()
{
	return sliderSineF6.GetPos();
}
int CVocoderGUIDlg::GetSineF7()
{
	return sliderSineF7.GetPos();
}

void CVocoderGUIDlg::OnBnClickedButtonUpdateModulator()
{
	int len = editModulator.GetWindowTextLengthW();
	WCHAR* dest = new WCHAR[len+1];
	editModulator.GetWindowTextW(dest, len+1);	
	lastText.assign(dest);
	delete dest;
}

bool CVocoderGUIDlg::IsRecording()
{
	return checkRecord.GetCheck()==BST_CHECKED;
}



void CVocoderGUIDlg::UpdateSettings(Settings* settings)
{
	if(!::IsWindow(m_hWnd))
	{
		return;
	}

	int streamSel = comboOutput.GetCurSel();
	settings->GetPlayer()->streamType = (Settings::PlayerSettings::StreamType) comboOutput.GetItemData(streamSel);
	//settings->GetPlayer()->shouldRecord = IsRecording();

	recorder->isListening = IsRecording();

	Settings::CarrierSettings* csettings = settings->GetCarrier();
	csettings->frequency = GetFrequency();
	csettings->frequencyVariation = GetFrequencyVariation();
	csettings->brownNoise = GetBrownNoise();
	csettings->whiteNoise = GetWhiteNoise();
	csettings->triangular = GetTriangular();
	csettings->square = GetSquare();
	csettings->sawtooth = GetSawtooth();
	csettings->sine = GetSine();
	csettings->freq2 = GetSineF2();
	csettings->freq3 = GetSineF3();
	csettings->freq4 = GetSineF4();
	csettings->freq5 = GetSineF5();
	csettings->freq6 = GetSineF6();
	csettings->freq7 = GetSineF7();
	csettings->random = GetRandom();
	csettings->function1 = GetFunction1();
	csettings->function2 = GetFunction2();
	csettings->function3 = GetFunction3();

	Settings::PitchTrackerSettings* psettings = settings->GetPitchTracker();
	TCHAR* s = GetTcharText(ptAmplitudeThreshold);
	double at = _wtof(s);
	if(at>0) 
	{
		psettings->amplitudeThreshold = at;
	}
	delete s;
	s = GetTcharText(ptNoiseThreshold);
	double nt = _wtof(s);
	if(nt>0) 
	{
		psettings->noiseThreshold = nt;
	}
	delete s;

}

void CVocoderGUIDlg::OnBnClickedButtonPlay()
{	
	controller->PlayOrStop();
}

void CVocoderGUIDlg::OnCbnSelchangeCombovoice()
{
	// TODO: Add your control notification handler code here
}
